home *** CD-ROM | disk | FTP | other *** search
- /* Our little helpers. Exported functions are prototyped in sundries.h.
- * $Header: /usr/src/mount/RCS/sundries.c,v 1.1 1992/09/06 13:30:53 root Exp root $
- */
-
- #include "sundries.h"
-
-
- /* File pointer for /etc/mtab. */
- FILE *F_mtab;
-
- /* File pointer for lock. */
- FILE *F_lock;
-
- /* File descriptor for lock. Value tested in unlock_mtab() to remove race. */
- int lock = -1;
-
- /* String list constructor. (car() and cdr() are defined in "sundries.h"). */
- string_list
- cons (char * const a, const string_list b)
- {
- string_list p;
-
- p = xmalloc (sizeof *p);
-
- car (p) = a;
- cdr (p) = b;
- return p;
- }
-
- void *
- xmalloc (size_t size)
- {
- void *t;
-
- if (size == 0)
- return NULL;
-
- t = malloc (size);
- if (t == NULL)
- die (2, "not enough memory");
-
- return t;
- }
-
- char *
- xstrdup (const char *s)
- {
- char *t;
-
- if (s == NULL)
- return NULL;
-
- t = strdup (s);
-
- if (t == NULL)
- die (2, "not enough memory");
-
- return t;
- }
-
- /* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
- void
- block_signals (int how)
- {
- sigset_t sigs;
-
- sigfillset (&sigs);
- sigprocmask (how, &sigs, (sigset_t *) 0);
- }
-
-
- /* Non-fatal error. Print message and return. */
- void
- error (const char *fmt, ...)
- {
- va_list args;
-
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
- va_end (args);
- }
-
- /* Fatal error. Print message and exit. */
- void volatile
- die (int err, const char *fmt, ...)
- {
- va_list args;
-
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
- va_end (args);
-
- exit (err);
- }
-
- /* Ensure that the lock is released if we are interrupted. */
- static void volatile
- handler (int sig)
- {
- die (2, "%s", sys_siglist[sig]);
- }
-
- /* Create the lock file. The lock file will be removed if we catch a signal
- or when we exit. The value of lock is tested to remove the race. */
- void
- lock_mtab (void)
- {
- int sig = 0;
- struct sigaction sa;
-
- /* If this is the first time, ensure that the lock will be removed. */
- if (lock < 0)
- {
- sa.sa_handler = handler;
- sigfillset (&sa.sa_mask);
-
- /* We should use sigismember() but it is broken for libc <= 4.2. */
- #if 0
- while (sigismember (&sa.sa_mask, ++sig) != -1)
- #else
- while (++sig < _NSIG)
- #endif
- sigaction (sig, &sa, (struct sigaction *) 0);
- }
-
- if ((lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0)
- die (2, "can't create lock file %s: %s", MOUNTED_LOCK, strerror (errno));
-
- F_lock = fdopen (lock, "w");
- }
-
- /* Remove lock file. */
- void
- unlock_mtab (void)
- {
- endmntent (F_lock);
- if (lock != -1)
- unlink (MOUNTED_LOCK);
- }
-
-
- /* Create mtab with a root entry. */
- static void
- create_mtab (void)
- {
- struct mntent *fstab;
-
- if ((F_mtab = setmntent (MOUNTED, "a+")) == NULL)
- die (1, "mount: can't open %s for writing: %s", MOUNTED, strerror (errno));
-
- /* Find the root entry by looking it up in fstab, which might be wrong.
- We could statfs "/" followed by a slew of stats on /dev/ but then
- we'd have to unparse the mount options as well.... */
- if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root")))
- {
- if (addmntent (F_mtab, fstab) == 1)
- die (1, "mount: error writing %s: %s", MOUNTED, strerror (errno));
- }
- if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
- endmntent (F_mtab);
- }
-
- /* Open mtab. */
- void
- open_mtab (const char *mode)
- {
- if (fopen (MOUNTED, "r") == NULL)
- create_mtab ();
- if ((F_mtab = setmntent (MOUNTED, mode)) == NULL)
- die (2, "can't open %s: %s", MOUNTED, strerror (errno));
- }
-
- /* Close mtab. */
- void
- close_mtab (void)
- {
- if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
- endmntent (F_mtab);
- }
-
- /* Parse a -t typelist into a string list. */
- string_list
- parse_types (char *types)
- {
- string_list list;
- char *t;
-
- if (types == NULL)
- return NULL;
-
- list = cons (strtok (types, ","), NULL);
-
- while ((t = strtok (NULL, ",")) != NULL)
- list = cons (t, list);
-
- return list;
- }
-
- /* True if fstypes match. Null *TYPES means match anything,
- except that swap types always return false. This routine
- has some ugliness to deal with ``no'' types. */
- int
- matching_type (const char *type, string_list types)
- {
- char *notype;
- int no; /* true if a "no" type match, ie -t nominix */
-
- if (streq (type, MNTTYPE_SWAP))
- return 0;
- if (types == NULL)
- return 1;
-
- if ((notype = alloca (strlen (type) + 3)) == NULL)
- die (2, "mount: out of memory");
- sprintf (notype, "no%s", type);
- no = (car (types)[0] == 'n') && (car (types)[1] == 'o');
-
- /* If we get a match and the user specified a positive match type (e.g.
- "minix") we return true. If we match and a negative match type (e.g.
- "nominix") was specified we return false. */
- while (types != NULL)
- if (streq (type, car (types)))
- return !no;
- else if (streq (notype, car (types)))
- return 0; /* match with "nofoo" always returns false */
- else
- types = cdr (types);
-
- /* No matches, so if the user specified a positive match type return false,
- if a negative match type was specified, return true. */
- return no;
- }
-
- /* Make a canonical pathname from PATH. Returns a freshly malloced string.
- It is up the *caller* to ensure that the PATH is sensible. i.e.
- canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
- is not a legal pathname for ``/dev/fd0.'' */
- char *
- canonicalize (const char *path)
- {
- char *canonical = xmalloc (PATH_MAX + 1);
- char *p = canonical;
-
- if (path == NULL)
- return NULL;
-
- if (streq (path, "none"))
- {
- strcpy (canonical, path);
- return canonical;
- }
- if (strchr (path, ':') != NULL)
- {
- strcpy(canonical, path);
- return canonical;
- }
- if (*path == '/')
- {
- /* We've already got an absolute path in PATH, but we need at
- least one char in canonical[] on entry to the loop below. */
- *p = *path++;
- }
- else
- {
- getcwd (canonical, PATH_MAX);
- p = canonical + strlen (canonical) - 1;
- if (*p != '/')
- *++p = '/';
- }
-
- /* There is at least one character in canonical[],
- and the last char in canonical[], *p, is '/'. */
- while ((*path != '\0') && (p < canonical + PATH_MAX))
- if (*p != '/')
- {
- *++p = *path++;
- }
- else
- {
- if (path[0] == '/')
- {
- path++; /* eliminate duplicate slashes (``//'') */
- }
- else if ((path[0] == '.') && ((path[1] == '\0') || (path[1] == '/')))
- {
- path++; /* eliminate ``/.'' */
- }
- else if ((path[0] == '.') && (path[1] == '.')
- && ((path[2] == '\0') || (path[2] == '/')))
- {
- while ((p > canonical) && (*--p != '/'))
- /* ascend on ``/../'' */
- ;
- path += 2;
- }
- else
- {
- *++p = *path++; /* not a special case, just copy char */
- }
- }
- if (p >= (canonical + PATH_MAX))
- die (2, "mount: path too long");
-
- if (*p == '/')
- --p; /* eliminate trailing slash */
-
- *++p = '\0';
-
- return canonical;
- }
-